package hikari.gui.guicomponents;

import com.gooddies.events.ValueChangedEvent;
import com.gooddies.graphics.InteractiveIcon;
import com.gooddies.wiring.Wiring;
import com.gooddies.wiring.annotations.PostWiring;
import com.gooddies.wiring.annotations.WiringComponent;
import hikari.gui.panels.ModifyPanel;
import hikari.utils.Utils;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;

/**
 * @author Dmitry
 */
@WiringComponent
public class ExpandablePanel extends JPanel {

    private TitledBorder border;
    private InteractiveIcon arrowIcon;
    private boolean expanded = true;
    private int previousHeight;
    private Rectangle arrowRectangle;
    private boolean arrowHightlighted = false;
    private ValueChangedEvent<Boolean> onExpandEvent;

    protected ExpandablePanel() {
    }

    @PostWiring
    private void init() {
        border = BorderFactory.createTitledBorder("Caption");
        border.setTitleJustification(TitledBorder.CENTER);
        setBorder(border);
        arrowIcon = new InteractiveIcon(Wiring.getComponent(Utils.class).loadImageFromResources("icons/arrowDown.png"));
        addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
                if (arrowRectangle.contains(e.getX(), e.getY())) {
                    if (!arrowHightlighted) {
                        arrowHightlighted = true;
                        repaint(arrowRectangle);
                    }
                } else {
                    if (arrowHightlighted) {
                        arrowHightlighted = false;
                        repaint(arrowRectangle);
                    }
                }
            }
        });

        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (arrowRectangle.contains(e.getX(), e.getY())) {
                    onArrowPress();
                    arrowIcon.mirrorVertical();
                }
            }
        });
    }

    public void setOnExpandPanel(ValueChangedEvent<Boolean> onExpandEvent) {
        this.onExpandEvent = onExpandEvent;
    }

    public void fireOnExpandEvent(boolean expanded) {
        if (onExpandEvent != null) {
            onExpandEvent.fire(expanded, this, false);
        }
    }

    @Override
    public void setBounds(int x, int y, int width, int height) {
        super.setBounds(x, y, width, height);
        arrowRectangle = new Rectangle(width - 20, 2, arrowIcon.getIconWidth(), arrowIcon.getIconHeight());
    }

    public boolean isExpanded() {
        return expanded;
    }

    @Override
    public Dimension getPreferredSize() {
        if (!isExpanded()) {
            return new Dimension(new Dimension(super.getPreferredSize().width, 20));
        }

        return super.getPreferredSize();
    }

    @Override
    public Dimension getMinimumSize() {
        if (!isExpanded()) {
            return new Dimension(new Dimension(super.getMinimumSize().width, 20));
        }
        return super.getMinimumSize();
    }

    @Override
    public Dimension getMaximumSize() {
        if (!isExpanded()) {
            return new Dimension(new Dimension(super.getMaximumSize().width, 20));
        }
        return super.getMaximumSize();
    }

    private void onArrowPress() {
        if (expanded) {
            collapse();
        } else {
            setPreferredSize(new Dimension(getPreferredSize().width, previousHeight));
            expanded = true;
            updateSizesInAncestors();
            fireOnExpandEvent(expanded);
        }
    }

    public void collapse() {
        previousHeight = getHeight();
        setPreferredSize(new Dimension(getPreferredSize().width, 20));
        expanded = false;
        updateSizesInAncestors();
        fireOnExpandEvent(expanded);
    }

    protected void updateSizesInAncestors() {
        updateSizes();
        if (getParent() instanceof ExpandablePanel) {
            ((ExpandablePanel) getParent()).updateSizesInAncestors();
        } else if (getParent() instanceof ModifyPanel) {
            ((ModifyPanel) getParent()).updateScroll();
        }
    }

    protected void updateSizes() {
        setPreferredSize(null);
        invalidate();
        validate();
        repaint();
    }

    public ExpandablePanel setTitle(String title) {
        if (border != null) {
            border.setTitle(title);
        }
        repaint();
        return this;
    }

    public ExpandablePanel setTitleColor(Color color) {
        border.setTitleColor(color);
        return this;
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        if (arrowHightlighted) {
            arrowIcon.getRolloverIcon().paintIcon(this, g, arrowRectangle.x, arrowRectangle.y);
        } else {
            arrowIcon.getDefaultIcon().paintIcon(this, g, arrowRectangle.x, arrowRectangle.y);
        }
    }
}
